chore: [ALT-268] DB ↔ 엔티티 스키마 일치화 작업#94
Conversation
- enum 필드 length 추가 (23건): User/EmailSendLog/Notification/Reputation 등 - String 필드 length 추가 (12건): File/ReputationSummary/SubstituteRequest 등 - 명시 length 정정 (3건): User.contact/Workspace.contact 13→11, ReputationRequest.requestType 20→24 - varchar↔text 일치화 (2건): UserCertificate.type/ReputationKeywordMap.description 총 40건의 엔티티 컬럼 length 정의 변경, 22개 파일. DDL_AUTO=validate에서 런타임 무영향. DB 마이그레이션 별도 처리.
- V2__align_entity_db_column_lengths.sql 신규 - email_send_logs.email varchar(255) → varchar(100) - user_certificates.type text → varchar(24) - reputation_keyword_map.description text → varchar(128) baseline-version: 1 기준, V2부터 적용. 로컬 DB에서 사전 검증 완료 (초과 데이터 없음).
|
Warning Review limit reached
More reviews will be available in 59 minutes and 5 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthrough여러 도메인 엔티티의 문자열 컬럼 길이 제약이 추가·수정되었고, 관련 3개 테이블의 실제 컬럼 타입을 맞추는 Flyway 마이그레이션이 추가되었습니다. Changes컬럼 길이 정렬
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 19
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/main/resources/db/migration/V2__align_entity_db_column_lengths.sql (1)
1-12: 🩺 Stability & Availability | 🔵 Trivial
email_send_logsALTER 시 잠금 시간 고려
ALTER COLUMN TYPE문 실행 시 PostgreSQL 는ACCESS EXCLUSIVE잠금을 획득하여 마이그레이션 완료 전까지 해당 테이블에 대한 모든 접근을 차단합니다.
email_send_logs는 일반적으로 고빈도 쓰기 트래픽이 발생하는 테이블이므로, 데이터 양이 많을 경우 잠금 시간이 길어져 서비스 중단 (Downtime) 으로 이어질 수 있습니다. 배포 전 반드시 DB 관리 명령어를 통해 해당 테이블의 실제 데이터 크기와 레코드 수를 확인하고, 충분한 유지보수 윈도우를 확보하시길 권장합니다.<comments>email_send_logs 테이블의 ALTER 연산은 생산 환경에서 락 관련 리스크가 있으므로 사전 확인이 필수적입니다.</comments>🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/resources/db/migration/V2__align_entity_db_column_lengths.sql` around lines 1 - 12, The `V2__align_entity_db_column_lengths.sql` migration changes `email_send_logs.email` with a direct `ALTER COLUMN TYPE`, which can hold an `ACCESS EXCLUSIVE` lock for a long time on a high-write table. Update the `email_send_logs` change to use a safer migration approach or at minimum add an explicit operational safeguard in this migration/workflow: verify table size and row count before running, and require a maintenance window. Keep the `user_certificates` and `reputation_keyword_map` changes as-is, but make the `email_send_logs` alteration clearly handled as the risky case.src/main/java/com/dreamteam/alter/domain/workspace/entity/SubstituteRequest.java (1)
41-64: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift이 변경은 도메인 모델의 JPA 결합도를 더 높입니다.
request_type,status, 사유/코멘트 길이 제약까지 도메인 엔티티에 직접 넣으면서 저장소 스키마가 도메인 타입에 더 깊게 스며들었습니다. 이 매핑 정보는 persistence 전용 모델로 분리하는 편이 맞습니다. As per path instructions,src/main/java/com/dreamteam/alter/domain/**는ZERO infrastructure dependencies (no Spring, no JPA annotations, no external libs)를 지켜야 합니다.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/java/com/dreamteam/alter/domain/workspace/entity/SubstituteRequest.java` around lines 41 - 64, Move the JPA mapping details out of SubstituteRequest because this domain entity now carries persistence concerns such as `@Enumerated`, `@Column` length constraints, and `@OneToMany`. Refactor the mapping so SubstituteRequest stays persistence-agnostic, and place the request_type/status/length metadata in a persistence-layer entity or mapping adapter instead. Use SubstituteRequest and its fields requestType, status, targets, requestReason, approverRejectionReason, and approvalComment as the reference points when extracting the JPA annotations.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/main/java/com/dreamteam/alter/domain/file/entity/File.java`:
- Around line 29-59: Add length validation to the File entity lifecycle methods
so oversized values fail early instead of at flush time. In File.create() and
File.attach(), validate targetId, storedKey, fileUrl, and contentType against
their column limits before assigning them, using a shared validateLength helper.
Keep the helper in File so the checks are centralized and throw a domain
exception when any value exceeds its defined length.
In
`@src/main/java/com/dreamteam/alter/domain/reputation/entity/ReputationKeywordMap.java`:
- Around line 41-42: The `ReputationKeywordMap.description` change to
`varchar(128)` is a shrinking migration, so validate existing production data
before applying it. Add a pre-migration check around the `description` column in
`ReputationKeywordMap` to confirm no rows exceed 128 characters, and ensure the
deployment/runbook includes taking a backup of `reputation_keyword_map` before
the schema change. If any overflow is found, handle it before proceeding with
the migration.
In `@src/main/java/com/dreamteam/alter/domain/user/entity/ManagerUser.java`:
- Line 34: The ManagerUser domain entity is still carrying JPA mapping metadata
on its status field, which violates the domain-layer path rules. Remove the
`@Column` length/nullable mapping from ManagerUser and keep persistence-specific
schema configuration in the persistence adapter or entity mapping layer instead,
so the domain model stays free of JPA annotations.
In `@src/main/java/com/dreamteam/alter/domain/user/entity/User.java`:
- Around line 44-45: The new contact length constraint conflicts with the
anonymization logic in User.withdraw(), where contact is set to id + "_탈퇴" and
can exceed 11 characters. Update the withdraw() masking rule so the anonymous
contact value always stays within 11 characters, using a shorter deterministic
format or truncation strategy tied to the User entity’s contact field
constraint. Make sure the change is applied in the withdraw() method and remains
compatible with the `@Column`(contact) length setting.
- Around line 44-55: The User entity is adding JPA schema constraints in the
domain layer, which conflicts with the path rule for
src/main/java/com/dreamteam/alter/domain/**. Remove persistence-specific
annotations and length-based column metadata from User, and keep only domain
invariants in the entity itself. If column sizing is still needed, move it to a
JPA mapping/model in the infrastructure layer or express the rule as a domain
validation without using JPA annotations. Refer to User and its field mappings
such as contact, birthday, gender, and role when updating the model.
In `@src/main/java/com/dreamteam/alter/domain/user/entity/UserCertificate.java`:
- Line 36: The UserCertificate domain entity is leaking persistence concerns by
declaring a JPA column length on the type field. Remove the `@Column` length
constraint from UserCertificate and keep the domain model free of JPA-specific
mapping details; if a length is needed for storage, move that responsibility to
the persistence mapping layer or entity-DTO/adapter configuration instead. Use
the UserCertificate entity as the location to clean up this infra coupling while
preserving its business invariants.
In
`@src/main/java/com/dreamteam/alter/domain/workspace/entity/BusinessInvitation.java`:
- Around line 41-42: Remove the JPA-specific mapping details from the
BusinessInvitation domain entity, since the domain layer must not depend on
persistence annotations or column metadata. Move the status mapping concerns,
including `@Enumerated`(EnumType.STRING) and the `@Column`(name = "status", length =
20, nullable = false) configuration, into the persistence/adapter model or JPA
entity that handles storage, keeping BusinessInvitation clean of
infrastructure-specific symbols.
In
`@src/main/java/com/dreamteam/alter/domain/workspace/entity/BusinessJoinRequest.java`:
- Around line 36-37: The BusinessJoinRequest domain entity is carrying
persistence-specific mapping details, which breaks the domain boundary. Remove
the JPA column length and other storage mapping concerns from the domain model
and move them to the infrastructure/persistence layer instead, keeping
BusinessJoinRequest free of JPA annotations while preserving the status field
mapping through a separate entity or adapter.
In
`@src/main/java/com/dreamteam/alter/domain/workspace/entity/SubstituteRequest.java`:
- Around line 58-64: SubstituteRequest currently only enforces the 500-character
limit at the JPA column level, while the domain methods still accept unbounded
strings. Update the invariants in the SubstituteRequest entity so that
create(...), approve(...), and rejectByApprover(...) validate or normalize
requestReason, approvalComment, and approverRejectionReason before assigning
them. Keep the business rule inside the entity methods themselves so the
500-character constraint is enforced as a domain invariant rather than failing
later at flush time.
In
`@src/main/java/com/dreamteam/alter/domain/workspace/entity/SubstituteRequestTarget.java`:
- Around line 32-36: The SubstituteRequestTarget entity is carrying JPA mapping
concerns that belong in the persistence layer, which violates the domain
boundary. Remove the JPA annotations and column constraints from this type, and
move the status/rejection_reason mapping details into the appropriate
persistence model or mapper while keeping SubstituteRequestTarget focused on
domain fields only.
- Around line 36-37: `SubstituteRequestTarget` currently relies on the database
column limit for `rejectionReason`, but the entity methods `reject(...)` and
`rejectByApprover(...)` can still assign overlong values directly. Add an
in-entity validation in `SubstituteRequestTarget` so the 500-character contract
is enforced before assignment, and apply it from both rejection methods to keep
the domain invariant inside the entity rather than at persistence time.
In `@src/main/java/com/dreamteam/alter/domain/workspace/entity/Workspace.java`:
- Line 42: The contact field constraint in Workspace is now narrower than the
current request and test data flow, so the existing phone format will pass
through CreateWorkspaceRequest and only fail at persistence. Fix this by either
preserving the current column length in Workspace or, if the 11-character limit
is intentional, adding normalization/validation inside Workspace.create(...) so
the domain enforces the invariant before saving. Use the Workspace entity and
its create(...) factory as the place to keep the business rule consistent with
CreateWorkspaceRequest and the existing fixtures.
In
`@src/main/java/com/dreamteam/alter/domain/workspace/entity/WorkspaceImage.java`:
- Around line 45-46: `WorkspaceImage`의 `fileId` 유효성 검사가 DB 컬럼 제약에만 의존하고 있습니다.
`create()` 팩토리 메서드에서 `fileId`의 null, blank, 그리고 정확히 36자 길이 여부를 검증하도록 추가하고, 위반 시
엔티티가 생성되지 않게 하세요. `WorkspaceImage.create`와 `fileId` 필드를 기준으로 찾아서 엔티티가 항상 유효한
상태로만 만들어지도록 수정하면 됩니다.
In
`@src/main/java/com/dreamteam/alter/domain/workspace/entity/WorkspaceRequestComment.java`:
- Around line 51-53: The WorkspaceRequestComment domain entity is carrying JPA
persistence details that should not live under domain. Remove the column width
constraint from the commentOwner mapping in WorkspaceRequestComment and move any
schema-specific configuration into the persistence layer model or mapper. Keep
only the business-facing CommentOwner field and its enum mapping in the domain
class, and ensure src/main/java/com/dreamteam/alter/domain/** remains free of
infrastructure-specific annotations or settings.
In
`@src/main/java/com/dreamteam/alter/domain/workspace/entity/WorkspaceRequestImage.java`:
- Line 42: WorkspaceRequestImage is missing domain invariant validation and
still exposes JPA infrastructure concerns. Update the create() factory in
WorkspaceRequestImage to validate fileId length 36 at construction time so
invalid values cannot enter the entity, and ensure the entity remains aligned
with domain rules instead of relying only on the database. Also review
WorkspaceRequestImage and related domain classes for jakarta.persistence
annotations like `@Entity` and `@Column`, and plan the separation of pure domain
model from persistence mapping so the domain layer no longer depends on
JPA/Spring infrastructure.
In
`@src/main/java/com/dreamteam/alter/domain/workspace/entity/WorkspaceShift.java`:
- Around line 38-40: The `WorkspaceShift` entity is mixing domain behavior with
persistence-specific mapping by hardcoding the enum column width in `status`.
Remove the `length` constraint from `WorkspaceShift` and keep only the domain
state-transition rules in this class, then move the enum storage/column sizing
concern into the persistence layer configuration or mapping for
`WorkspaceShiftStatus` so `src/main/java/com/dreamteam/alter/domain/**` stays
free of infrastructure details.
In
`@src/main/java/com/dreamteam/alter/domain/workspace/entity/WorkspaceWorker.java`:
- Around line 37-39: Remove the storage-specific column length from the
WorkspaceWorker status field so the domain entity does not encode JPA
persistence constraints. Update WorkspaceWorker’s status mapping to keep only
the business-relevant state definition via WorkspaceWorkerStatus and move any
length or similar database tuning to the persistence layer mapping, ensuring
src/main/java/com/dreamteam/alter/domain/** stays free of
infrastructure-specific details.
In
`@src/main/java/com/dreamteam/alter/domain/workspace/entity/WorkspaceWorkerSchedule.java`:
- Around line 50-65: The `WorkspaceWorkerSchedule` domain entity is carrying
persistence-specific column width concerns for `DayOfWeek` and schedule status.
Remove the `length` constraints from the enum-related `@Column` mappings in
`WorkspaceWorkerSchedule` and move any storage-width/serialization configuration
into the persistence layer or JPA mapping configuration. Keep the entity focused
on domain rules such as `validTime` and `validOverlappingTime`, and ensure the
`status` and day-of-week fields remain domain-level properties without
infrastructure-specific sizing details.
In `@src/main/resources/db/migration/V2__align_entity_db_column_lengths.sql`:
- Around line 5-7: The migration for UserCertificate.type should remain aligned
with the entity mapping by keeping the column change from text to varchar(24) in
the V2__align_entity_db_column_lengths.sql script and ensuring the
UserCertificate entity still uses `@Column`(length = 24). Verify the
CertificateType enum values stay within the 24-character limit so the ALTER
COLUMN in this migration remains safe and consistent with the model.
---
Outside diff comments:
In
`@src/main/java/com/dreamteam/alter/domain/workspace/entity/SubstituteRequest.java`:
- Around line 41-64: Move the JPA mapping details out of SubstituteRequest
because this domain entity now carries persistence concerns such as `@Enumerated`,
`@Column` length constraints, and `@OneToMany`. Refactor the mapping so
SubstituteRequest stays persistence-agnostic, and place the
request_type/status/length metadata in a persistence-layer entity or mapping
adapter instead. Use SubstituteRequest and its fields requestType, status,
targets, requestReason, approverRejectionReason, and approvalComment as the
reference points when extracting the JPA annotations.
In `@src/main/resources/db/migration/V2__align_entity_db_column_lengths.sql`:
- Around line 1-12: The `V2__align_entity_db_column_lengths.sql` migration
changes `email_send_logs.email` with a direct `ALTER COLUMN TYPE`, which can
hold an `ACCESS EXCLUSIVE` lock for a long time on a high-write table. Update
the `email_send_logs` change to use a safer migration approach or at minimum add
an explicit operational safeguard in this migration/workflow: verify table size
and row count before running, and require a maintenance window. Keep the
`user_certificates` and `reputation_keyword_map` changes as-is, but make the
`email_send_logs` alteration clearly handled as the risky case.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: ea7dd508-c9f5-46c4-8181-38153062b655
📒 Files selected for processing (23)
src/main/java/com/dreamteam/alter/domain/email/entity/EmailSendLog.javasrc/main/java/com/dreamteam/alter/domain/file/entity/File.javasrc/main/java/com/dreamteam/alter/domain/notification/entity/Notification.javasrc/main/java/com/dreamteam/alter/domain/posting/entity/PostingApplication.javasrc/main/java/com/dreamteam/alter/domain/reputation/entity/Reputation.javasrc/main/java/com/dreamteam/alter/domain/reputation/entity/ReputationKeywordMap.javasrc/main/java/com/dreamteam/alter/domain/reputation/entity/ReputationRequest.javasrc/main/java/com/dreamteam/alter/domain/reputation/entity/ReputationSummary.javasrc/main/java/com/dreamteam/alter/domain/user/entity/ManagerUser.javasrc/main/java/com/dreamteam/alter/domain/user/entity/User.javasrc/main/java/com/dreamteam/alter/domain/user/entity/UserCertificate.javasrc/main/java/com/dreamteam/alter/domain/workspace/entity/BusinessInvitation.javasrc/main/java/com/dreamteam/alter/domain/workspace/entity/BusinessJoinRequest.javasrc/main/java/com/dreamteam/alter/domain/workspace/entity/SubstituteRequest.javasrc/main/java/com/dreamteam/alter/domain/workspace/entity/SubstituteRequestTarget.javasrc/main/java/com/dreamteam/alter/domain/workspace/entity/Workspace.javasrc/main/java/com/dreamteam/alter/domain/workspace/entity/WorkspaceImage.javasrc/main/java/com/dreamteam/alter/domain/workspace/entity/WorkspaceRequestComment.javasrc/main/java/com/dreamteam/alter/domain/workspace/entity/WorkspaceRequestImage.javasrc/main/java/com/dreamteam/alter/domain/workspace/entity/WorkspaceShift.javasrc/main/java/com/dreamteam/alter/domain/workspace/entity/WorkspaceWorker.javasrc/main/java/com/dreamteam/alter/domain/workspace/entity/WorkspaceWorkerSchedule.javasrc/main/resources/db/migration/V2__align_entity_db_column_lengths.sql
withdraw()에서 id + "_탈퇴" 익명화 값을 안전하게 담기 위해: - User.name: varchar(12) → varchar(30) - User.contact: varchar(11) → varchar(30) - Flyway 마이그레이션 V3 추가 장기적 암호화 저장 도입 시의 암호문 길이도 함께 고려.
변경사항
https://app.notion.com/p/38a8655316288130a60be648150aab0e
엔티티 컬럼 length 정의 일치화 (22개 파일, 40건)
Flyway 마이그레이션 (V2) 추가
마이그레이션 적용 검증 완료 (로컬 DB 데이터 길이 초과 없음, 서버 기동 시 Flyway validation/migration 성공)
Summary by CodeRabbit
Bug Fixes
Chores